package com.syezon.wifikey.speed;

import android.arch.lifecycle.MutableLiveData;
import android.arch.lifecycle.ViewModel;

import com.blankj.utilcode.util.LogUtils;
import com.syezon.wifikey.speed.config.SpeedConfig;
import com.xiaoli.speedtestlib.core.Speedtest;
import com.xiaoli.speedtestlib.core.serverSelector.TestPoint;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

public class NewSpeedTestViewModel extends ViewModel {

    private static final String TAG = SpeedTestViewModel.class.getSimpleName();

    private SpeedTestStepInfo speedTestStepInfo = new SpeedTestStepInfo();
    private MutableLiveData<SpeedTestStepInfo> speedTestStepInfoMutableLiveData = new MutableLiveData<>();
    private Speedtest speedtest = new Speedtest();
    private boolean finishDownload, finishUpload;
    private boolean sendStartDl, sendStartUp;
    private volatile boolean cancel;

    public MutableLiveData<SpeedTestStepInfo> getSpeedTestStepInfoMutableLiveData() {
        return speedTestStepInfoMutableLiveData;
    }

    public NewSpeedTestViewModel() {
        String speedTestUrl = SpeedConfig.getSpeedTestUrl();
        URL url = null;
        try {
            url = new URL(speedTestUrl);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        String protocol = url.getProtocol();
        String host = url.getHost();
        String path = url.getPath();
        speedtest.setSelectedServer(new TestPoint("云测节点", protocol + "://" + host, path, path, path, path));
    }

    public void startSpeedTest() {
        new Thread() {
            @Override
            public void run() {
                final List<Double> downloadSampleList = new ArrayList<>();
                final List<Double> unloadSampleList = new ArrayList<>();
                cancel = false;
                speedTestStepInfo.setStepType(SpeedTestStepInfo.STEP_TYPE_INIT);
                speedtest.abort();
                finishDownload = false;
                finishUpload = false;
                sendStartUp = false;
                sendStartDl = false;
                speedTestStepInfo.setStepType(SpeedTestStepInfo.STEP_TYPE_START_PING_TEST);
                speedTestStepInfoMutableLiveData.postValue(speedTestStepInfo);
                speedtest.start(new Speedtest.SpeedtestHandler() {
                    @Override
                    public void onDownloadUpdate(double dl, long total, double progress) {
                        LogUtils.eTag(TAG, "onDownloadUpdate -> dl: " + dl + "progress: " + progress);
                        if (progress < 0.95) {
                            if (progress >= 0.1 && !sendStartDl) {
                                sendStartDl = true;
                                speedTestStepInfo.setStepType(SpeedTestStepInfo.STEP_TYPE_START_SPEED);
                                speedTestStepInfoMutableLiveData.postValue(speedTestStepInfo);
                                try {
                                    Thread.sleep(500);
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }
                            }
                            if (sendStartDl) {
                                //current_speed
                                speedTestStepInfo.setStepType(SpeedTestStepInfo.STEP_TYPE_CURRENT_SPEED);
                                speedTestStepInfo.setDownloadSpeed(dl);
                                if (dl > 0 && downloadSampleList.size() < 32) {
                                    downloadSampleList.add(dl);
                                }
                                if (downloadSampleList.size() >= 32 && dl > 0) {
                                    downloadSampleList.remove(31);
                                    downloadSampleList.add(dl);
                                }
                                speedTestStepInfo.setDownloadSampleList(downloadSampleList);
                                speedTestStepInfoMutableLiveData.postValue(speedTestStepInfo);
                            }
                        } else {
                            //end_speed
                            if (!finishDownload) {
                                finishDownload = true;
                                speedTestStepInfo.setStepType(SpeedTestStepInfo.STEP_TYPE_AVERAGE_SPEED);
                                speedTestStepInfo.setDownloadSpeed(dl);
                                speedTestStepInfo.setDownloadDataUse(total);
                                speedTestStepInfo.setDownloadSpeed(dl);
                                if (dl > 0 && downloadSampleList.size() < 32) {
                                    downloadSampleList.add(dl);
                                }
                                if (downloadSampleList.size() < 32) {
                                    for (int i = downloadSampleList.size(); i < 32; i++) {
                                        downloadSampleList.add(dl);
                                    }
                                }
                                speedTestStepInfo.setDownloadSampleList(downloadSampleList);
                                speedTestStepInfoMutableLiveData.postValue(speedTestStepInfo);
                            }
                        }
                    }

                    @Override
                    public void onUploadUpdate(double ul, long total, double progress) {
                        LogUtils.eTag(TAG, "onUploadUpdate -> dl: " + ul + "progress: " + progress);
                        if (progress < 0.95) {
                            //current_upload
                            if (progress >= 0.1 && !sendStartUp) {
                                sendStartUp = true;
                                speedTestStepInfo.setStepType(SpeedTestStepInfo.STEP_TYPE_START_UPLOAD);
                                speedTestStepInfoMutableLiveData.postValue(speedTestStepInfo);
                                try {
                                    Thread.sleep(500);
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }
                            }
                            if (sendStartUp) {
                                speedTestStepInfo.setStepType(SpeedTestStepInfo.STEP_TYPE_CURRENT_UPLOAD);
                                speedTestStepInfo.setUploadSpeed(ul);
                                if (ul > 0 && unloadSampleList.size() < 32) {
                                    unloadSampleList.add(ul);
                                }
                                if (unloadSampleList.size() >= 32 && ul > 0) {
                                    unloadSampleList.remove(31);
                                    unloadSampleList.add(ul);
                                }
                                speedTestStepInfo.setUploadSampleList(unloadSampleList);
                                speedTestStepInfoMutableLiveData.postValue(speedTestStepInfo);
                            }
                        } else {
                            //end_upload
                            if (!finishUpload) {
                                finishUpload = true;
                                speedTestStepInfo.setStepType(SpeedTestStepInfo.STEP_TYPE_AVERAGE_UPLOAD);
                                speedTestStepInfo.setUploadSpeed(ul);
                                speedTestStepInfo.setUploadDataUse(total);
                                if (ul > 0 && unloadSampleList.size() < 32) {
                                    unloadSampleList.add(ul);
                                }
                                if (unloadSampleList.size() < 32) {
                                    for (int i = unloadSampleList.size(); i < 32; i++) {
                                        unloadSampleList.add(ul);
                                    }
                                }
                                speedTestStepInfo.setUploadSampleList(unloadSampleList);
                                speedTestStepInfoMutableLiveData.postValue(speedTestStepInfo);
                            }

                        }
                    }

                    @Override
                    public void onPingJitterUpdate(double ping, double jitter, double loseRate, double progress) {
                        LogUtils.eTag(TAG, "onPingJitterUpdate -> ping: " + ping + " jitter: " + jitter + "progress: " + progress);
                        speedTestStepInfo.setStepType(SpeedTestStepInfo.STEP_TYPE_PING_RESULT);
                        speedTestStepInfo.setPingData(new SpeedTestStepInfo.PingData(ping, jitter, loseRate));
                        speedTestStepInfoMutableLiveData.postValue(speedTestStepInfo);
                    }

                    @Override
                    public void onLoseRateUpdate(double loseRate, double progress) {
                        if (progress >= 1) {
                            speedTestStepInfo.setStepType(SpeedTestStepInfo.STEP_TYPE_LOSE_RATE_RESULT);
                            speedTestStepInfo.setLoseRate(loseRate);
                            speedTestStepInfoMutableLiveData.postValue(speedTestStepInfo);
                        } else {
                            speedTestStepInfo.setStepType(SpeedTestStepInfo.STEP_TYPE_START_LOSE_RATE_RESULT);
                            speedTestStepInfoMutableLiveData.postValue(speedTestStepInfo);
                        }

                    }

                    @Override
                    public void onIPInfoUpdate(String ipInfo) {
                        LogUtils.eTag(TAG, "onIPInfoUpdate -> ipInfo: " + ipInfo);
                    }

                    @Override
                    public void onTestIDReceived(String id, String shareURL) {
                        LogUtils.eTag(TAG, "onTestIDReceived -> id: " + id + "shareURL: " + shareURL);
                    }

                    @Override
                    public void onEnd() {
                        LogUtils.eTag(TAG, "onEnd");
                    }

                    @Override
                    public void onCriticalFailure(String err) {
                        LogUtils.eTag(TAG, "onCriticalFailure -> err: " + err);
                        speedTestStepInfo.setStepType(SpeedTestStepInfo.STEP_TYPE_ERROR);
                        speedTestStepInfoMutableLiveData.postValue(speedTestStepInfo);
                    }
                });
            }
        }.start();

    }

    public void endSpeedTest() {
        cancel = true;
        speedtest.abort();
        finishUpload = false;
        finishDownload = false;
        speedTestStepInfo.setStepType(SpeedTestStepInfo.STEP_TYPE_CANCEL);
        speedTestStepInfoMutableLiveData.postValue(speedTestStepInfo);
    }
}
